package edu.hcmus.sow.web.user;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import edu.hcmus.sow.dao.UserDAO;
import edu.hcmus.sow.dao.UserProfileDAO;
import edu.hcmus.sow.domain.User;
import edu.hcmus.sow.domain.UserProfile;
import edu.hcmus.sow.domain.security.CustomUser;
import edu.hcmus.sow.service.UserService;
import edu.hcmus.sow.utils.SecurityUtil;

@Controller
@RequestMapping
public class UserController {
   @Autowired
   private UserDAO userDAO;

   @Autowired
   private UserProfileDAO userProfileDAO;

   @Autowired
   private UserService userService;

   /**
    * Show all User entities
    * 
    */
   @RequestMapping("/list")
   public ModelAndView listUsers() {
      ModelAndView mav = new ModelAndView();

      mav.addObject("users", userDAO.findAll());

      mav.setViewName("listUsers");

      return mav;
   }

   /**
    * Create a new User entity
    * 
    */
   @RequestMapping("/new")
   public ModelAndView newUser() {
      ModelAndView mav = new ModelAndView();

      mav.addObject("userForm", new UserForm());
      mav.addObject("newFlag", true);
      mav.setViewName("editUser");
      return mav;
   }

   /**
    * Save an existing User entity
    * 
    */
   @RequestMapping("/save")
   public String saveUser(@Valid UserForm userForm, BindingResult result) {
      validate(userForm.getUsername(), result);

      if (result.hasErrors()) {
         return "editUser";
      }

      User user = new User();
      user.setId(userForm.getId());
      user.setUsername(userForm.getUsername());
      user.setPassword(userForm.getPassword());
      user.setEnabled(userForm.getEnabled());

      userService.saveUser(user);
      return "forward:/user/list";
   }

   /**
    * Edit an existing User entity
    * 
    */
   @RequestMapping("/edit")
   public ModelAndView editUser(@RequestParam("idKey") Integer idKey) {
      ModelAndView mav = new ModelAndView();
      User user = userDAO.findById(idKey);
      UserForm userForm = new UserForm(user.getId(), user.getUsername(), user.getPassword(), user.getEnabled());

      mav.addObject("userForm", userForm);
      mav.setViewName("editUser");

      return mav;
   }

   @RequestMapping(value = "/ajax/user/search", produces = "application/json")
   @ResponseBody
   public List<Map<String, String>> getUsers(@RequestParam("approver") String name) {

      Integer clientID = SecurityUtil.getCurrentClient();
      List<UserProfile> list = userProfileDAO.findByName(clientID, name);

      List<Map<String, String>> items = new ArrayList<Map<String, String>>();
      for (UserProfile u : list) {
         Map<String, String> item = new HashMap<String, String>();
         item.put("id", u.getUserByUserId().getId().toString());
         item.put("name", u.getFirstName() + " " + u.getLastName());
         item.put("username", " (" + u.getUserByUserId().getUsername() + ")");
         items.add(item);
      }
      return items;
   }

   // ~ Methods
   // ========================================================================================================
   private void validate(String username, Errors errors) {
      if (!errors.hasFieldErrors("username")) {
         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
         int clientID = ((CustomUser) authentication.getPrincipal()).getClientID();

         if (userDAO.findByUsername(username, clientID) != null) {
            errors.rejectValue("username", "err.username", "Username exists.");
         }
      }
   }
}
